package com.hockeo.client.metadata;

import java.util.Map;

import com.google.gwt.core.client.GWT;

/**
 * Provides access to metadata for any class that is tagged with the marker interface
 * {@link IMetadataTag}.
 *
 * @version $Id$
 * @author jjanke
 */
public abstract class MetadataFactory
{
  private static MetadataFactory           d_instance;
  private final Map<Class<?>, Metadata<?>> d_map;

  /**
   * Creates a new MetadataFactory instance.
   */
  protected MetadataFactory()
  {
    d_map = createMetadata();
  }

  /**
   * Returns the singleton MetadataFactory instance.
   */
  public static MetadataFactory get()
  {
    if ( d_instance == null )
      if ( GWT.isClient() )
        d_instance = GWT.create( MetadataFactory.class );

    return d_instance;
  }

  /**
   * Returns the metadata matching the given class that must implement the
   * {@link IMetadataTag} interface.
   *
   * @param <T> the type of the class for which is described by the metadata
   * @param cls the class for which is described by the metadata
   * @return the requested metadata
   * @throws IllegalStateException if there is no metadata available
   */
  @SuppressWarnings( "unchecked" )
  public final <T extends IMetadataTag> Metadata<T> getMetadata( Class<T> cls )
  {
    Metadata<T> metadata = (Metadata<T>) d_map.get( cls );

    if ( metadata == null )
      throw new IllegalStateException( "No metadata is available for class '" + cls.getName() + "'." );

    return metadata;
  }

  protected abstract Map<Class<?>, Metadata<?>> createMetadata();
}
